package com.edu.exam.entity.assessment;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

/**
 * 组卷方案实体类
 * 所属模块：B-03 试卷管理模块
 * 对应数据库表：grouping_scheme
 *
 * <p>组卷方案管理子模块的核心实体，用于存储组卷方案的基本信息。
 * 支持方案的完整生命周期管理，包括创建、配置、使用、状态变更等全过程。
 * 专注于组卷方案的制定、配置和管理，为后续的组卷执行提供标准化、规范化的组卷策略和规则。</p>
 *
 * @author 系统生成
 * @version 2.0
 * @since 2025-11-09
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@EntityListeners(AuditingEntityListener.class)
public class GroupingScheme {

    /**
     * 主键ID
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /**
     * 方案编码
     *
     * <p>组卷方案的唯一编码，用于方案的标识和检索。
     * 编码规则建议：SCHEME_ + 课程编码 + 时间戳 + 序号。</p>
     */
    @Column(name = "scheme_code", nullable = false, length = 50)
    private String schemeCode;

    /**
     * 方案名称
     *
     * <p>组卷方案的名称，应简洁明了地描述方案的主要特征和用途。
     * 例如：Java程序设计期末考试组卷方案、计算机网络期中考试组卷方案等。</p>
     */
    @Column(name = "scheme_name", nullable = false, length = 200)
    private String schemeName;

    /**
     * 方案描述
     *
     * <p>详细描述组卷方案的内容、适用场景、组卷要求等信息。
     * 包括组卷的知识点范围、难度分布、题型结构等关键信息。</p>
     */
    @Column(name = "scheme_desc", columnDefinition = "TEXT")
    private String schemeDesc;

    /**
     * 课程编码
     *
     * <p>关联课程的编码，标识该组卷方案适用的具体课程。
     * 需要与课程信息表中的课程编码保持一致。</p>
     */
    @Column(name = "course_code", nullable = false, length = 50)
    private String courseCode;

    /**
     * 总分
     *
     * <p>试卷的总分值，默认为100分。
     * 可根据实际考试需求进行调整，如120分、150分等。</p>
     */
    @Column(name = "total_score", nullable = false)
    private Integer totalScore = 100;

    /**
     * 考试时长（分钟）
     *
     * <p>考试的持续时间，单位为分钟。
     * 默认为120分钟（2小时），可根据课程特点和考试要求进行调整。</p>
     */
    @Column(name = "exam_duration", nullable = false)
    private Integer examDuration = 120;

    /**
     * 状态
     *
     * <p>组卷方案的当前状态，支持以下状态值：
     * - DRAFT: 草稿状态，方案正在创建或编辑过程中
     * - ACTIVE: 激活状态，方案已正式启用，可用于组卷操作
     * - INACTIVE: 停用状态，方案暂时停止使用，但保留数据
     * - ARCHIVED: 归档状态，方案已过期或废弃，进入历史归档</p>
     */
    @Column(name = "status", nullable = false, length = 20)
    private String status = "DRAFT";

    /**
     * 创建人ID
     *
     * <p>创建组卷方案的用户ID，关联系统用户表。
     * 用于记录方案的责任人和权限控制。</p>
     */
    @Column(name = "creator_id", nullable = false)
    private Long creatorId;

    /**
     * 创建人姓名
     *
     * <p>创建组卷方案的用户姓名，用于显示和记录。
     * 冗余存储用户姓名，避免频繁关联查询用户表。</p>
     */
    @Column(name = "creator_name", nullable = false, length = 100)
    private String creatorName;

    /**
     * 配置数据
     *
     * <p>JSON格式的配置数据，存储方案的详细配置信息。
     * 包括知识点配置、难度配置、题型配置、分值配置等。
     * 使用JSON格式提供灵活的配置扩展能力。</p>
     */
    @Column(name = "config_data", columnDefinition = "TEXT")
    private String configData;

    /**
     * 使用次数
     *
     * <p>方案被使用的总次数，用于统计方案的使用频次和热度。
     * 每次使用该方案进行组卷时，此计数器自动递增。</p>
     */
    @Column(name = "use_count", nullable = false)
    private Integer useCount = 0;

    /**
     * 最后使用时间
     *
     * <p>方案最后一次被使用的时间，用于记录方案的使用历史。
     * 可用于方案的活跃度分析和优化建议。</p>
     */
    @Column(name = "last_use_time")
    private LocalDateTime lastUseTime;

    /**
     * 是否删除
     *
     * <p>逻辑删除标识，false表示未删除，true表示已删除。
     * 使用软删除机制，保留历史数据用于审计和统计。</p>
     */
    @Column(name = "is_deleted", nullable = false)
    private Boolean isDeleted = false;

    // ===== 审计字段 =====

    /**
     * 创建时间
     */
    @CreatedDate
    @Column(name = "created_time", nullable = false, updatable = false)
    private LocalDateTime createdTime;

    /**
     * 更新时间
     */
    @LastModifiedDate
    @Column(name = "updated_time", nullable = false)
    private LocalDateTime updatedTime;

    /**
     * 创建人
     */
    @Column(name = "created_by", length = 50)
    private String createdBy;

    /**
     * 更新人
     */
    @Column(name = "updated_by", length = 50)
    private String updatedBy;

}